# -*- coding: utf-8 -*-
# @Create On    : 2020/7/28 20:36
# @Author  : Bao Linfeng
# @Function    : TODO To debug:
# @File    : DataPreProcessingWindows.py
# @Software: PyCharm
import os

from datetime import datetime, date
import matplotlib.pyplot as plt

from PyQt5.QtCore import QThread, pyqtSignal, Qt, QDate
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QDialog, QApplication
import distro
from GnssLogUtils import SplitNmeaData
from ui_calendar_select import Ui_Dialog
from ui_data_pre_processing import Ui_DataPreProcess


from ImuConverter import ImuDataProcess, OutputOption


# self.Output = None


class ImuDecodeThread(QThread):
    finishSignal = pyqtSignal(int)
    logSignal = pyqtSignal(str)

    def __init__(self, imu_type: int, in_path: str, out_path: str, rate: int):
        super(ImuDecodeThread, self).__init__()
        self.imu_type = imu_type
        self.in_path = in_path
        self.out_path = out_path
        self.rate = rate
        self.decoders = {0: "exec/stim300_decoder", 1: "exec/wit_decoder", 2: "", 3: ""}

    def run(self):
        print("imu decode...")
        if os.path.isfile(self.decoders[self.imu_type]):
            os.system(
                "{} -in_file {} -out_file {} -rate {}".format(self.decoders[self.imu_type], self.in_path, self.out_path,
                                                              self.rate))
            self.finishSignal.emit(1)
        else:
            print("decoder is not exist,please compile decoder file, and copy to \"exec\"")
            self.logSignal.emit("decoder is not exist,please compile decoder file, and copy to \"exec\"")


class DecodeThread(QThread):
    finishSignal = pyqtSignal(SplitNmeaData)

    def __init__(self, s: SplitNmeaData):
        """
        :param file_path: 文件路径
        :param columns: 列数（只对bin文件有效）
        :param dtype: 数据类型（只对bin文件有效）
        :param mode: 模式 bin或者ascii
        :param ascii_types:数据类型 0表示屏蔽，1表示启用
        """
        super(DecodeThread, self).__init__()
        self.s = s

    def run(self):
        self.s.splitData()
        self.finishSignal.emit(self.s)


class CalendarDialog(QDialog, Ui_Dialog):
    date_signal = pyqtSignal(QDate)

    def __init__(self):
        # super(self.CalendarDialog, self).__init__()
        super(CalendarDialog, self).__init__()
        self.setupUi(self)
        # self.exec_()

    def accept(self) -> None:
        selected_date = self.calendarWidget.selectedDate()
        self.date_signal.emit(selected_date)
        return QDialog.accept(self)

    def reject(self):
        return QDialog.reject(self)


class DataPreProcessingWindow(QMainWindow, Ui_DataPreProcess):
    def __init__(self):
        super(DataPreProcessingWindow, self).__init__()
        self.setupUi(self)
        self.btn_browse_gnss.clicked.connect(self.on_btn_browse_gnss)
        self.btn_decode.clicked.connect(self.on_btn_decode)
        self.btn_calendar.clicked.connect(self.on_btn_calendar)
        self.btn_browse_imu.clicked.connect(self.on_btn_browse_imu)
        self.btn_decode_imu.clicked.connect(self.onBtnDecodeIMU)
        self.btn_close_plot.clicked.connect(self.on_close_plot)
        self.edit_imu_path.textChanged.connect(self.onEditRawImuChanged)

        self.btn_convert.clicked.connect(self.onBtnIMUConvert)
        self.btn_plot.clicked.connect(self.on_btn_plot_imu)

        # self.btn_open_dir.clicked.connect(self.on_btn_open_output_dir)
        self.thread = None
        self.outputdir = None
        self.dlg = None

    def onEditRawImuChanged(self):
        text = self.edit_imu_path.text()
        if os.path.isfile(text):
            self.edit_out_imu_path.setText(text + ".imutxt")

    def on_btn_open_output_dir(self):
        imu_file_path = self.edit_imu_path.text()
        if not os.path.isfile(imu_file_path):
            self.show_log("Error: no such file %s" % imu_file_path)
            return

        if distro.linux_distribution()[0] == 'Deepin':
            os.system("dde-file-manager %s" % imu_file_path)
        else:
            self.show_log("only deepin os is supported")

    def on_btn_browse_imu(self):
        filfilepath, suffix = QFileDialog.getOpenFileName(
            filter='All Files (*)')
        if suffix == "":
            return

        self.edit_imu_path.setText(filfilepath)
        self.show_log("output path: %s" % filfilepath)

    def onBtnDecodeIMU(self):
        """
        bin和ascii文本文件相互转换
        :return:
        """
        opt = OutputOption()
        opt.imuFile = self.edit_imu_path.text()
        if not os.path.isfile(opt.imuFile):
            self.show_log("Error: no such file %s" % opt.imuFile)
        opt.imuType = self.comb_type_2.currentIndex()
        opt.OutputFilePath = self.edit_out_imu_path.text()
        opt.OutputMode = self.output_mode.currentIndex()
        opt.OutputFrame = self.comb_output_frame.currentIndex()
        opt.OutputAcceUnit = self.cmb_acce_out_unit.currentIndex()
        opt.OutputGyroUnit = self.cmb_gyro_out_unit.currentIndex()

        opt.Rate = self.imu_rate.value()
        print("imu rate :%d" % opt.Rate)
        self.thread = ImuDecodeThread(opt.imuType, opt.imuFile, opt.OutputFilePath, opt.Rate)
        self.thread.logSignal.connect(self.show_log)
        self.thread.finishSignal.connect(self.onIMUdDecodeFinished)
        self.thread.start()
        self.btn_decode_imu.setEnabled(False)

    def onIMUdDecodeFinished(self, res: int):
        if res > 0:
            self.show_log("decode finished")
        self.btn_decode_imu.setEnabled(True)
        self.edit_imu_path_2.setText(self.edit_out_imu_path.text())

    def onBtnIMUConvert(self):
        from ImuConverter import ImuDataConvert
        file_path = self.edit_imu_path_2.text()
        if not os.path.isfile(file_path):
            self.show_log("no such file %s" % file_path)
            return
        convert_frame = self.comb_in_frame.currentIndex() == self.comb_output_frame.currentIndex()
        idc = ImuDataConvert()
        if self.comb_imu_fmt.currentIndex() == 0:
            idc.read_imuraw(file_path)

        if self.comb_imu_fmt.currentIndex() == 1:
            idc.read_imutxt(file_path)

        if self.comb_imu_fmt.currentIndex() == 2:
            idc.read_imd(file_path)

        if self.output_mode.currentIndex() == 0:
            rate = self.imu_rate_2.value()
            out_path = self.edit_imu_output_path_2.text()
            self.show_log("convert to %s" % out_path)
            idc.to_imd(out_path, rate, 9.8, convert_frame=convert_frame)

        if self.output_mode.currentIndex() == 1:
            rate = self.imu_rate_2.value()
            out_path = self.edit_imu_output_path_2.text()
            self.show_log("convert to %s" % out_path)
            idc.to_imutxt(out_path, rate, 9.8, convert_frame=convert_frame)

        self.show_log("convert finished")

    def onOutputModeChanged(self):
        idx = self.output_mode.currentIndex()
        if idx == 0:
            self.edit_imu_output_path_2.setText(self.edit_imu_path_2.text()+".imd")
        if idx == 1:
            self.edit_imu_output_path_2.setText(self.edit_imu_path_2.text() + ".imutxt")

    def on_btn_browse_gnss(self):
        filfilepath, suffix = QFileDialog.getOpenFileName(filter='Log files(*.log);;All Files (*)')
        if suffix == "":
            return
        # if re.match('.*.log', filfilepath):
        #     self.comb_file_type.setCurrentIndex(0)
        self.edit_gnss_path.setText(filfilepath)
        self.show_log("input file path: %s" % filfilepath)

    def on_btn_calendar(self):
        self.dlg = CalendarDialog()
        self.dlg.date_signal.connect(self.on_show_date)
        self.dlg.show()

    def on_btn_plot_imu(self):
        imu_file_path = self.edit_imu_path_2.text()
        if not os.path.isfile(imu_file_path):
            self.show_log("Error: no such file %s" % imu_file_path)
        file_type = self.comb_imu_fmt.currentIndex()
        convert_frame = self.comb_output_frame.currentIndex() == self.comb_in_frame.currentIndex()
        s = ImuDataProcess(imu_file_path, file_type, convert_frame)
        if s.e is not None:
            self.show_log(s.e.args[0])
            return
        plt.close("all")
        plt.figure("gyro")
        font_dict ={'family': 'Times New Roman', 'size': 14}
        times = s.data[:, 0]
        plt.plot(times - times[0], s.data[:, 1], 'r')
        plt.plot(times - times[0], s.data[:, 2], 'g')
        plt.plot(times - times[0], s.data[:, 3], 'b')
        plt.xlabel("gps second/s - %f" % times[0])
        plt.ylabel("gyro /rad")
        plt.legend(["x", "y", "z"])
        plt.title("gyroscope")
        plt.figure("acce")
        plt.plot(times - times[0], s.data[:, 4], 'r')
        plt.plot(times - times[0], s.data[:, 5], 'g')
        plt.plot(times - times[0], s.data[:, 6], 'b')
        plt.xlabel("gps second/s - %f" % times[0])
        plt.ylabel("acce /m/s")
        plt.legend(["x", "y", "z"])
        plt.title("accelerator")

        plt.figure("time check")
        plt.plot(times[1:] - times[0], s.time_diff[:], 'r')
        plt.yticks(fontproperties=font_dict["family"], size=10)
        plt.xticks(fontproperties=font_dict["family"], size=10)
        plt.xlabel("GPS second/s - %f" % times[0],fontdict=font_dict)
        plt.ylabel("time diff /s",fontdict=font_dict)
        plt.show()

    def on_close_plot(self):
        plt.close("all")

    def on_show_date(self, selected_date: QDate):
        print(selected_date)
        self.show_log("choose date:%s" % selected_date.toString("yyyy/MM/dd"))
        self.edit_date.setDate(selected_date)

    def on_btn_decode(self):
        filepath = self.edit_gnss_path.text()
        if not os.path.isfile(filepath):
            self.show_log("file %s doesn't exit")
            return

        # get option from ui
        opt = SplitNmeaData.Option()
        opt.file_type = 1#  int(self.comb_file_type.currentIndex())
        opt.data_type = 1# int(self.comb_type.currentIndex())
        opt.gga = self.cbx_gga.checkState() == Qt.Checked
        opt.gsv = self.cbx_gsv.checkState() == Qt.Checked
        opt.hdt = self.cbx_hdt.checkState() == Qt.Checked
        opt.rmc = self.cbx_rmc.checkState() == Qt.Checked
        opt.kxst = self.cbx_ksxt.checkState() == Qt.Checked
        opt.rangea = self.cbx_ranga.checkState() == Qt.Checked
        opt.rangeha = self.cbx_rangha.checkState() == Qt.Checked
        qdate = self.edit_date.date()
        opt.date = date(qdate.year(), qdate.month(), qdate.day())
        # d = datetime.date(opt.date)

        s = SplitNmeaData(filepath, opt)
        self.thread = DecodeThread(s)
        self.thread.finishSignal.connect(self.onDecodeFinished)
        self.thread.start()
        self.btn_decode.setEnabled(False)

    def onDecodeFinished(self, s: SplitNmeaData):
        self.btn_decode.setEnabled(True)
        if s.exception is not None:
            self.show_log("error:%s" % str(s.exception))
        self.show_log("decode finished")

    def show_log(self, msg):
        stamp = datetime.now().strftime('%H:%M:%S : ')
        item = stamp + msg
        self.listLog.addItem(item)

    def clear_log(self):
        self.listLog.clear()


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    w = DataPreProcessingWindow()
    w.show()
    sys.exit(app.exec_())
